#include "RunAction.hh"

#include "AtomNumFilter.hh"
#include "AtomNumFilterMsgr.hh"
#include "G4RunManager.hh"
#include "G4ScoringManager.hh"
#include "MyMacros.hh"
// #include "LETdMessenger.hh"
// #include "RgProjScorerMsgr.hh"
// #include "G4UnitsTable.hh"
// #include "PrimaryGeneratorAction.hh"
// #include "Randomize.hh"
// #include "globals.hh"
// #include <iomanip>
// #include "DetectorConstruction.hh"
using std::make_unique;

RunAction::RunAction()
{
    //MYG4TID(tid);
    //DINFOLN("[tid {} RunAction] RunAction()", tid);
    G4RunManager::GetRunManager()->SetPrintProgress(5000);
    _fAtomNumFilterMsgr = new AtomNumFilterMsgr(_fAtomNSFilterVec);
}

void RunAction::BeginOfRunAction(const G4Run*)
{
    MYG4TID(tid);
    DINFOLN("[tid {} RunAction] BeginOfRunAction()", tid);
    _seed0 = std::chrono::high_resolution_clock::now();  // tik tok

#if 0
    /// 在 worker 上注册 LETdMessenger
    //if (!_fLETdMessengerWorker)
    {
        _fLETdMessengerWorker = make_unique<LETdMessenger>();
        DINFOLN("```````````````````````````````````[tid {} RunAction/BeginOfRunAction] LETdMessenger instantiated on Worker", tid);
    }
#endif

#if 0
    //if (!_rgProjScorerMsgrWorker)
    {
        DINFOLN("```````````````````````````````````[tid {} RunAction/BeginOfRunAction] RgProjScorerMsgr instantiated on Worker", tid);
        _rgProjScorerMsgrWorker = make_unique<RgProjScorerMsgr>();
    }
#endif

    ///xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    G4ScoringManager* scManager = G4ScoringManager::GetScoringManager();
    if (scManager)
    {
        const G4int num_mesh = scManager->GetNumberOfMesh();
        const auto& filter_vec = _fAtomNumFilterMsgr->GetFilterVec();
        DINFOLN("[tid {} RunAction/BeginOfRunAction]RunAction: Now scManager has {} meshes", tid, num_mesh);

        //G4VScoringMesh* mesh = scManager->GetCurrentMesh();
        for (int ix = 0; ix < num_mesh; ++ix)
        {
            G4VScoringMesh* mesh = scManager->GetMesh(ix);
            if (mesh)
            {
#if 0
                /// 将自定义的filter与该score mesh关联
                /// TODO: 如果宏文件中mesh没有设置filter, 则需要加判断, 避免setfilter时错位
                G4cout << "RunAction::BeginOfRunAction: fAtomNSFilter address " << _fAtomNSFilterVec << G4endl;

                if (_fAtomNumFilterMsgr->GetFilter())
                {
                    //G4cout << "RunAction::BeginOfRunAction: fAtomNSFilterMessenger::GetFilter address " << fAtomNSFilterMessenger->GetFilter() << G4endl;
                    //mesh->SetFilter(fAtomNSFilter);
                    mesh->SetFilter(_fAtomNumFilterMsgr->GetFilter());
                }
#endif
                if (filter_vec[ix])
                {
                    mesh->SetFilter(filter_vec[ix]);
                    DINFOLN("[tid {} RunAction/BeginOfRunAction] Applied AtomNumScoreFilter to mesh {}", tid, ix);
                }
            }
            else
            {
                DINFOLN("[tid {} RunAction/BeginOfRunAction] AScore mesh {} was not found!", tid, ix);
            }
        }
    }
}

void RunAction::EndOfRunAction(const G4Run*)
{
    MYG4TID(tid);
    // G4cout << "[RunAction End] End of run action\n";
    //================================== calculation time
    _seed1 = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double, std::milli> elapsed = _seed1 - _seed0;
    LINFO("[tid {:>4d} EndOfRunAction] Cost {:>13.4F} ms", tid, elapsed.count());
    //G4cout << "[RunAction End] Calculation time           = " << G4BestUnit(difftime(_seed1, _seed0), "Time") << " \n" << G4endl;
}
